home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / scd113.arc / DEMO1.C next >
Text File  |  1990-06-14  |  19KB  |  723 lines

  1. /*************************************************
  2.  **                                             **
  3.  **   demo1.c                                   **
  4.  **                                             **
  5.  **   SoftC (tm) Dbase Library                  **
  6.  **        Address List Demo Program            **
  7.  **           Copyright (C) 1989 by             **
  8.  **               Kim Schumann                  **
  9.  **               16820 3rd St NE               **
  10.  **               Ham Lake, MN 55304            **
  11.  **               (612) 434-6968                **
  12.  **                                             **
  13.  **             All rights reserved.            **
  14.  *************************************************/
  15.  
  16.  
  17.  
  18.  
  19.  
  20. /*
  21.           The Address  List Program is a simple program which will create a
  22.           database (CUSTOMER.DBF)  and two index files. The database record
  23.           contains the following fields:
  24.  
  25.  
  26.           field name     type length    description
  27.           ----------     ---- ------    -----------
  28.           CODE            N    10.0     customer code
  29.           DATE            D     8       date added to file
  30.           FIRSTNAME       C    15       first name
  31.           LASTNAME        C    25       last name
  32.           COMPANY         C    40       company name
  33.           ADDRESS         C    30       street address, po box, etc
  34.           CITY            C    20       city
  35.           STATE           C     2       state
  36.           ZIPCODE         C     5       5 digit zip code
  37.           AREACODE        C     3       telephone area code
  38.           TELEPHONE       C     8       telephone number
  39.           EXTENSION       C     4       telephone extension
  40.  
  41.  
  42.           The index  files created  are: CUSTCODE.NDX  (customer code), and
  43.           CUSTNAME.NDX (customer last name).
  44.  
  45.  
  46.           The program  has two main functions: Update/Add new addresses and
  47.           List contents of database. It also supports a "Quit" command.
  48.  
  49.  
  50.           The Update  function enables the user to either add a new or find
  51.           an existing  record. The  Add subfunction  displays a  data entry
  52.           screen and  then the  user steps  through the  fields filling the
  53.           blanks as  required (use  Control Z  to end  Add mode).  The Find
  54.           subfunction allows  the user  to select what the search type will
  55.           be: CODE  or LASTNAME.  Once the data to be searched for has been
  56.           entered, the  user will be allowed to scroll forward and backward
  57.           through the  data. After the data record has been found, the user
  58.           is allowed to edit or delete the data record (and keys).
  59.  
  60.  
  61.           The List  function allows  the user  to select where data will be
  62.           displayed   (Printer/Screen)   and   how   to   sort   the   data
  63.           (Code/Name/Unsorted).  The   "CODE",  "LASTNAME",  and  "COMPANY"
  64.           fields of each data record are displayed.
  65.  
  66.  
  67.           Seventeen lines  of data  are output to the screen as a page. The
  68.           user is then prompted to continue the display or abort. Data sent
  69.           to the printer is continuous with no headings or page numbers.
  70.  
  71.  
  72.           The program  as it  stands is  barely useable  as an address list
  73.           manager but  its real  value is  in the  demonstration of certain
  74.           library functions.  However, it  could form  the basis  of a full
  75.           featured address list manager, or ...
  76.  
  77.  */
  78.  
  79.  
  80.  
  81.  
  82. /*
  83.  *  header files
  84.  */
  85.  
  86. #include <sc_base.h>
  87. #include <string.h>
  88. #include <conio.h>
  89. #include <stdio.h>
  90. #include <stdlib.h>
  91. #include <ctype.h>
  92. #if !defined(__TURBOC__)
  93. #include <graph.h>
  94. #endif
  95.  
  96.  
  97. #if !defined(__TURBOC__)
  98. #define gotoxy(x,y); _settextposition(y,x);
  99. #define clrscr(); _clearscreen(_GCLEARSCREEN);
  100. #endif
  101.  
  102. /*
  103.  *  global variables
  104.  */
  105.  
  106. SC_FIELD fields[] = {
  107.   "Code", 'n', 10, 0,           /* code */
  108.   "Date", 'd', 8, 0,            /* entry date */
  109.   "FirstName", 'c', 15, 0,      /* first name */
  110.   "LastNAme", 'c', 25, 0,       /* last name */
  111.   "Company", 'c', 40, 0,        /* company name */
  112.   "Address", 'c', 30, 0,        /* street address, po box, etc */
  113.   "City", 'c', 20, 0,           /* city */
  114.   "State", 'c', 2, 0,           /* state */
  115.   "ZipCode", 'c', 5, 0,         /* 5 digit zip code */
  116.   "AreaCode", 'c', 3, 0,        /* area code */
  117.   "telePhone", 'c', 8, 0,       /* telephone number */
  118.   "ExTenSion", 'c', 4, 0        /* telephone extension */
  119. };
  120.  
  121. char dbf, ndx1, ndx2, d[101];
  122. char icterm[] = {15,9,13,26,0}, fterm[] = {13,0};
  123.  
  124.  
  125. /*
  126.  *  function prototypes
  127.  */
  128.  
  129. void main( void );
  130. void select(char *, char *, char *);
  131. void update( void );
  132. void list( void );
  133. void clearscreen( void );
  134. void add( void );
  135. void find( void );
  136. void clearform( void );
  137. void inputdata( void );
  138. void outputdata( void );
  139. char inputstr( char *, char, char, char, char * );
  140. #if !defined(__TURBOC__)
  141. void clreol( void );
  142. #endif
  143.  
  144.  
  145. #if !defined(__TURBOC__)
  146. /* clreol function for microsoftc */
  147.  
  148. void clreol()
  149. {
  150.   struct rccoord rcoord;
  151.   char i;
  152.  
  153.   rcoord = _gettextposition();
  154.   for (i=(char) rcoord.col; i<80; i++)
  155.     putch(' ');
  156.   _settextposition(rcoord.row,rcoord.col);
  157. }
  158. #endif
  159.  
  160.  
  161.  
  162. /*
  163.  *  select will display "msg" starting at column 1 and row 23. It will then
  164.  *  wait for keyboard input verifying keystrokes against "inver". When a key
  165.  *  has been pressed which could be found in the verify string that character
  166.  *  is returned in "ch". Invalid keystrokes are beeped.
  167.  */
  168.  
  169. void select(msg, inver, ch)
  170. char *msg, *inver, *ch;
  171. {
  172.   gotoxy(1,23);
  173.   printf("%s",msg);
  174.   gotoxy(strlen(msg) + 1,23);
  175.   clreol();
  176.   do {
  177.     *ch = (char) getch();
  178.     *ch = toupper(*ch);
  179.     if (strchr(inver,*ch) != NULL)
  180.       break;
  181.     putch(7);
  182.   } while (1 != 2);
  183.   putch(*ch);
  184. }
  185.  
  186.  
  187.  
  188. /*
  189.  *  clearscreen will erase the center part of the screen.
  190.  */
  191.  
  192. void clearscreen()
  193. {
  194.   char i;
  195.  
  196.   for (i=4; i<22; i++) {
  197.     gotoxy(1,i);
  198.     clreol();
  199.   }
  200. }
  201.  
  202.  
  203.  
  204. /*
  205.  *  clearform will clear the field data entry portion of the screen. The field
  206.  *  names and other text will remain.
  207.  */
  208.  
  209. void clearform()
  210. {
  211.   gotoxy(7,5); printf("%10c",' ');
  212.   gotoxy(42,5); clreol();
  213.   gotoxy(13,7); printf("%15c",' ');
  214.   gotoxy(41,7); clreol();
  215.   gotoxy(15,9); clreol();
  216.   gotoxy(10,11); clreol();
  217.   gotoxy(7,12); printf("%20c",' ');
  218.   gotoxy(37,12); printf("  ");
  219.   gotoxy(50,12); clreol();
  220.   gotoxy(13,14); printf("   )   -    ");
  221.   gotoxy(41,14); clreol();
  222. }
  223.  
  224.  
  225.  
  226.  
  227. /*
  228.  *  inputstr will display the current contents of the field ("data") at the
  229.  *  proper position on the screen ("x" column, "y" row). It will then wait
  230.  *  for keyboard input. The routine processes the "right arrow" and "left
  231.  *  arrow" keys (keypad) to nondestructively move within the field, "delete"
  232.  *  will delete the character where the cursor is, and "backspace" deletes
  233.  *  the character immediately to the left of the cursor. "length" determines
  234.  *  how much data can be entered, and "term" contains a list of special
  235.  *  characters which will cause inputstr to return to caller.
  236.  */
  237.  
  238. char inputstr(data,length,x,y,term)
  239. char *data,length,x,y,*term;
  240. {
  241.   char p = 0, ch;
  242.  
  243.   gotoxy(x,y);
  244.   printf("%s",data);
  245.   do {
  246.     gotoxy(x+p,y);
  247.     ch = (char) getch();
  248.     switch (ch) {
  249.       case 0:
  250.         ch = (char) getch();
  251.         switch (ch) {
  252.           case 15:  /* Shift TAB */
  253.             break;
  254.           case 75:  /* Left Arrow */
  255.             if (p > 0)
  256.               p--;
  257.             else
  258.               putch(7);
  259.             break;
  260.           case 77:  /* Right Arrow */
  261.             if (p < (char) strlen(data))
  262.               p++;
  263.             else
  264.               putch(7);
  265.             break;
  266.           case 83:  /* Delete Key */
  267.             memmove(data+p,data+p+1,length-p);
  268.             data[length - 1] = 0;
  269.             gotoxy(x,y);
  270.             printf("%s",data);
  271.             break;
  272.           default:
  273.             putch(7);
  274.             break;
  275.         }
  276.         break;
  277.       case 8: /* Back Space */
  278.         if (p > 0) {
  279.           memmove(data+p-1,data+p,length-p);
  280.           gotoxy(x,y);
  281.           printf("%s",data);
  282.           p--;
  283.         }
  284.         else
  285.           putch(7);
  286.         break;
  287.       default:
  288.         if (strchr(term,ch) == NULL) {
  289.           if ((ch < 32) || (ch > 126) || (p >= length))
  290.             putch(7);
  291.           else {  /* normal character input */
  292.             if (strlen(data) == length)
  293.               data[length - 1] = 0;
  294.             memmove(data+p+1,data+p,length-p);
  295.             data[p] = ch;
  296.             gotoxy(x,y);
  297.             printf("%s",data);
  298.             p++;
  299.           }
  300.         }
  301.         break;
  302.     }
  303.   } while (strchr(term,ch) == NULL);
  304.   return(ch);
  305. }
  306.  
  307.  
  308.  
  309. /*
  310.  *  inputdata calls inputstr successively for each field in the database
  311.  *  record. This routine will process "tab", "shift tab", "carriage return",
  312.  *  and "control z" (all done with record).
  313.  */
  314.  
  315. void inputdata()
  316. {
  317.   char tc, n, *p;
  318.   double t;
  319.  
  320.   n = 0;
  321.   do {
  322.     sceclr();
  323.     scdrcopy(dbf,SC_OUTPUT);
  324.     scdfgets(dbf,n,d);
  325.     p = d;
  326.     switch(n) {
  327.       case 0:
  328.         tc = inputstr(d,10,7,5,icterm);
  329.         t = atof(d);
  330.         p = (char *) &t;
  331.         break;
  332.       case 1:
  333.         sccdxlat(d,d,SC_2ASCII);
  334.         tc = inputstr(d,8,42,5,icterm);
  335.         break;
  336.       case 2:
  337.         tc = inputstr(d,15,13,7,icterm);
  338.         break;
  339.       case 3:
  340.         tc = inputstr(d,25,41,7,icterm);
  341.         break;
  342.       case 4:
  343.         tc = inputstr(d,40,15,9,icterm);
  344.         break;
  345.       case 5:
  346.         tc = inputstr(d,30,10,11,icterm);
  347.         break;
  348.       case 6:
  349.         tc = inputstr(d,20,7,12,icterm);
  350.         break;
  351.       case 7:
  352.         tc = inputstr(d,2,37,12,icterm);
  353.         break;
  354.       case 8:
  355.         tc = inputstr(d,5,50,12,icterm);
  356.         break;
  357.       case 9:
  358.         tc = inputstr(d,3,13,14,icterm);
  359.         break;
  360.       case 10:
  361.         tc = inputstr(d,8,17,14,icterm);
  362.         break;
  363.       case 11:
  364.         tc = inputstr(d,4,41,14,icterm);
  365.         break;
  366.     }
  367.     if (scdfput(dbf,n,p) < SC_SUCCESS)
  368.       tc = 0;
  369.     if ((tc == 9) || (tc == 13)) {  /* tab or carriage return */
  370.       if (n == 11)
  371.         n = 0;
  372.       else
  373.         n++;
  374.     }
  375.     else if (tc == 15) {    /* translated shift tab */
  376.       if (n == 0)
  377.         n = 11;
  378.       else
  379.         n--;
  380.     }
  381.   } while (tc != 26); /* control Z */
  382. }
  383.  
  384.  
  385. /*
  386.  *  outputdata displays each field of the record along with its name.
  387.  */
  388.  
  389. void outputdata()
  390. {
  391.   gotoxy(1,5); scdfgets(dbf,0,d); printf("Code: %s",d);
  392.   gotoxy(30,5); scdfget(dbf,1,d); printf("Entry Date: %s",d);
  393.   gotoxy(1,7); scdfgets(dbf,2,d); printf("First Name: %s",d);
  394.   gotoxy(30,7); scdfgets(dbf,3,d); printf("Last Name: %s",d);
  395.   gotoxy(1,9); scdfgets(dbf,4,d); printf("Company Name: %s",d);
  396.   gotoxy(1,11); scdfgets(dbf,5,d); printf("Address: %s",d);
  397.   gotoxy(1,12); scdfgets(dbf,6,d); printf("City: %s",d);
  398.   gotoxy(30,12); scdfgets(dbf,7,d); printf("State: %s",d);
  399.   gotoxy(40,12); scdfgets(dbf,8,d); printf("Zip Code: %s",d);
  400.   gotoxy(1,14); scdfgets(dbf,9,d); printf("Telephone: (%s)",d);
  401.   gotoxy(17,14); scdfgets(dbf,10,d); printf("%s",d);
  402.   gotoxy(30,14); scdfgets(dbf,11,d); printf("Extension: %s",d);
  403. }
  404.  
  405.  
  406.  
  407. /*
  408.  *  add will solicit a new record, verify that it is new, and if new add
  409.  *  the data record and keys.
  410.  */
  411.  
  412. void add()
  413. {
  414.   long r;
  415.   char *k;
  416.   double c;
  417.  
  418.   sceclr();
  419.   do {
  420.     scdrclear(dbf,SC_OUTPUT);
  421.     inputdata();
  422.     scdfgetx(dbf,0,&c,SC_OUTPUT);
  423.     if (scdkfind(ndx1,(char *) &c,&r,SC_FIRST) == SC_SUCCESS) {
  424.       gotoxy(6,19);
  425.       printf("ERROR - Duplicate customer code %c",7);
  426.     }
  427.     else
  428.       break;
  429.   } while ( 1 != 2 );
  430.   scdrput(dbf,&r,SC_ADD);
  431.   scdkmake(dbf,ndx1,(void **) &k);
  432.   scdkadd(ndx1,k,r);
  433.   free(k);
  434.   scdkmake(dbf,ndx2,(void **) &k);
  435.   scdkadd(ndx2,k,r);
  436.   free(k);
  437. }
  438.  
  439.  
  440. /*
  441.  *  find allows user to select which index to search with, to enter a key
  442.  *  so search for, to single step through index (forward and backward), and
  443.  *  finally to edit (or delete) the selected record.
  444.  */
  445.  
  446. void find()
  447. {
  448.   char ch, *k, *l, n1[26], n2[26], field, index;
  449.   long r;
  450.   double c1, c2;
  451.  
  452.   sceclr();
  453.   scdrclear(dbf,SC_OUTPUT);
  454.   select("Find by: C)ode, N)ame","CN",&ch);
  455.   d[0] = 0;
  456.   switch (ch) {
  457.     case 'C':
  458.       ch = inputstr(d,10,7,5,fterm);
  459.       c1 = atof(d);
  460.       l = (char *) &c1;
  461.       field = 0;
  462.       index = ndx1;
  463.       break;
  464.     case 'N':
  465.       ch = inputstr(d,25,41,7,fterm);
  466.       l = d;
  467.       field = 3;
  468.       index = ndx2;
  469.       break;
  470.   }
  471.   scdfput(dbf,field,l);
  472.   scdkmake(dbf,index,(void **) &l);
  473.   if (scdkfind(index,l,&r,SC_FIRST) == SC_SUCCESS) {
  474.     do {
  475.       scdrget(dbf,r);
  476.       outputdata();
  477.       select("Find: N)ext, P)revious, Q)uit","NPQ",&ch);
  478.       switch (ch) {
  479.         case 'N':
  480.           scdknext(index,l,&r);
  481.           break;
  482.         case 'P':
  483.           scdkprev(index,l,&r);
  484.           break;
  485.       }
  486.     } while ((ch != 'Q') && (sc_code >= SC_SUCCESS));
  487.  
  488.     if (sc_code >= SC_SUCCESS) {
  489.       select("Find: E)dit, D)elete, Q)uit","EDQ",&ch);
  490.       switch (ch) {
  491.         case 'E':
  492.         /* save old data (keys) */
  493.           scdfget(dbf,0,&c1);
  494.           scdfget(dbf,3,n1);
  495.         /* edit record */
  496.           scdrcopy(dbf,SC_INPUT);
  497.           inputdata();
  498.         /* check if keyed data changed */
  499.           scdfgetx(dbf,0,&c2,SC_OUTPUT);
  500.           scdfgetx(dbf,3,n2,SC_OUTPUT);
  501.           if ((c1 != c2) || (strcmp(n1,n2) != 0)) {
  502.           /* delete old keys */
  503.             scdfput(dbf,0,&c1);
  504.             scdfput(dbf,3,n1);
  505.             scdkmake(dbf,ndx1,(void **) &k);
  506.             scdkdel(ndx1,k,r);
  507.             free(k);
  508.             scdkmake(dbf,ndx2,(void **) &k);
  509.             scdkdel(ndx2,k,r);
  510.             free(k);
  511.           /* add new keys */
  512.             scdfput(dbf,0,&c2);
  513.             scdfput(dbf,3,n2);
  514.             scdkmake(dbf,ndx1,(void **) &k);
  515.             scdkadd(ndx1,k,r);
  516.             free(k);
  517.             scdkmake(dbf,ndx2,(void **) &k);
  518.             scdkadd(ndx2,k,r);
  519.             free(k);
  520.           }
  521.           scdrput(dbf,&r,SC_UPDATE);
  522.           break;
  523.         case 'D':
  524.           scdkmakex(dbf,ndx1,(void **) &k,SC_INPUT);
  525.           scdkdel(ndx1,k,r);
  526.           free(k);
  527.           scdkmakex(dbf,ndx2,(void **) &k,SC_INPUT);
  528.           scdkdel(ndx2,k,r);
  529.           free(k);
  530.           scdrdel(dbf,r);
  531.           break;
  532.       }
  533.     }
  534.   }
  535.   free(l);
  536. }
  537.  
  538.  
  539.  
  540. /*
  541.  *  update allows user to select whether to add a new record or to find and
  542.  *  existing record.
  543.  */
  544.  
  545. void update()
  546. {
  547.   char ch;
  548.   long r;
  549.  
  550.   scdrclear(dbf,SC_INPUT);
  551.   outputdata();
  552.   do {
  553.     select("Update: A)dd, F)ind, Q)uit","AFQ",&ch);
  554.     switch(ch) {
  555.       case 'A':
  556.         add();
  557.         break;
  558.       case 'F':
  559.         find();
  560.         break;
  561.     }
  562.     if (ch != 'Q') {
  563.       gotoxy(60,2);
  564.       scddsize(dbf,&r);
  565.       printf("%5ld Records in use",r);
  566.       clearform();
  567.     }
  568.   } while (ch != 'Q');
  569. }
  570.  
  571.  
  572. /*
  573.  *  list allows user to display records on the screen or on a printer, and to
  574.  *  select which index to use (if any). If displaying on the screen it will
  575.  *  pause to enable you to view the data. list will show only the active data
  576.  *  in the file. In other words, records previously deleted will not be
  577.  *  displayed even though they are still physically in the database.
  578.  */
  579.  
  580. void list()
  581. {
  582.   char co, cs, ch, lc;
  583.   long r;
  584.  
  585.   select("Output device: P)rinter, S)creen","PS",&co);
  586.   select("Sort by: C)ode, N)ame, U)nsorted","CNU",&cs);
  587.   gotoxy(1,23);
  588.   printf("Press <Esc> to abort");
  589.   gotoxy(21,23);  /* printf does not change textposition in MSC */
  590.   clreol();
  591.   sceclr();
  592.   if (cs == 'C')
  593.     scdkfirst(ndx1,d,&r);
  594.   else if (cs == 'N')
  595.     scdkfirst(ndx2,d,&r);
  596.   else
  597.     r = 1L;
  598.   lc = 4;
  599.   do {
  600.     if (kbhit())
  601.       if (getch() == 27)
  602.         return;
  603.     scdrget(dbf,r);
  604.     if (sc_code == SC_SUCCESS) {
  605.       if (co == 'P') {
  606.         scdfgets(dbf,0,d);
  607.         fprintf(stdprn,"%s",d);
  608.         scdfgets(dbf,3,d);
  609.         fprintf(stdprn,"%s",d);
  610.         scdfgets(dbf,4,d);
  611.         fprintf(stdprn,"%s\n",d);
  612.       }
  613.       else {
  614.         if (lc == 21) {
  615.           gotoxy(1,23);
  616.           printf("Press <RETURN> to continue or <Esc> to abort");
  617.           gotoxy(45,23);
  618.           clreol();
  619.           do {
  620.             ch = (char) getch();
  621.           } while ((ch != 13) || (ch != 27));
  622.           if (ch == 27)
  623.             return;
  624.           gotoxy(1,23);
  625.           printf("Press <Esc> to abort");
  626.           gotoxy(21,23);
  627.           clreol();
  628.           clearscreen();
  629.           lc = 4;
  630.         }
  631.         gotoxy(1,lc);
  632.         scdfgets(dbf,0,d);
  633.         printf("%s",d);
  634.         gotoxy(11,lc);
  635.         scdfgets(dbf,3,d);
  636.         printf("%s",d);
  637.         gotoxy(42,lc);
  638.         scdfgets(dbf,4,d);
  639.         printf("%s",d);
  640.         lc++;
  641.       }
  642.     }
  643.     switch (cs) {
  644.       case 'C':
  645.         scdknext(ndx1,d,&r);
  646.         break;
  647.       case 'N':
  648.         scdknext(ndx2,d,&r);
  649.         break;
  650.       case 'U':
  651.         r += 1L;
  652.         break;
  653.     }
  654.   } while ((sc_code != SC_END) && (sc_code >= SC_SUCCESS));
  655.   if (co == 'S') {
  656.     gotoxy(1,23);
  657.     printf("Press <RETURN>");
  658.     gotoxy(15,23);
  659.     clreol();
  660.     do {
  661.       ch = (char) getch();
  662.     } while (ch != 13);
  663.   }
  664. }
  665.  
  666.  
  667. /*
  668.  *  main opens the data and index files (or creates them if they do not exist).
  669.  *  The user can then select whether to update the contents of the database,
  670.  *  or to display them.
  671.  */
  672.  
  673. void main()
  674. {
  675.   char line[80], ch;
  676.   long r;
  677.  
  678.   scdinit(20);
  679.   memset(line,'-',79);
  680.   line[79] = 0;
  681.   clrscr();
  682.   puts(line);
  683.   puts("SoftC Demonstration Database");
  684.   puts(line);
  685.   gotoxy(1,22);
  686.   printf("%s\n\n%s",line,line);
  687.   gotoxy(1,4);
  688.   if ((scddopen(&dbf,"Customer.dbf") == SC_SUCCESS) &&
  689.       (scdnopen(&ndx1,"custcode.ndx") == SC_SUCCESS))
  690.     scdnopen(&ndx2,"custname.ndx");
  691.   if (sc_code < SC_SUCCESS) {
  692.     select("Data files missing. Create new files (Y/N)","YN",&ch);
  693.     if (ch == 'Y') {
  694.       sceclr();
  695.       scddcreate("Customer.dbf",12,fields);
  696.       scdncreate("CUSTCODE.NDX",'N',"CODE",8);
  697.       scdncreate("CUSTNAME.NDX",'c',"lastname",25);
  698.       if ((scddopen(&dbf,"Customer.dbf") == SC_SUCCESS) &&
  699.           (scdnopen(&ndx1,"custcode.ndx") == SC_SUCCESS))
  700.         scdnopen(&ndx2,"custname.ndx");
  701.       if (sc_code < SC_SUCCESS)
  702.         exit(1);
  703.     }
  704.     else
  705.       exit(1);
  706.   }
  707.   gotoxy(60,2);
  708.   scddsize(dbf,&r);
  709.   printf("%5ld Records in use",r);
  710.   do {
  711.     select("Select: U)pdate, L)ist, Q)uit","ULQ",&ch);
  712.     switch (ch) {
  713.       case 'U':
  714.         update();
  715.         break;
  716.       case 'L':
  717.         list();
  718.         break;
  719.     }
  720.     clearscreen();
  721.   } while (ch != 'Q');
  722.   scdterm();
  723. }